package pattern.config;

import com.alicp.jetcache.CacheGetResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import pattern.annontations.Secure;
import pattern.cache.InitCache;
import pattern.constant.CacheKeyConstant;
import pattern.constant.DefaultSystemConstant;
import pattern.currentsession.ContextLocalCache;
import pattern.currentsession.ParentLocale;
import pattern.currentsession.PatternContext;
import pattern.result.ResponseData;
import pattern.result.ResponseResultStatus;
import pattern.utils.CollectionUtil;
import pattern.utils.JwtUtil;
import pattern.utils.ServletTool;
import pattern.utils.SpringTool;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;

/**
 * 设置微服务会话 用户信息
 * @author Simon
 */
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class FeignInterceptor implements AsyncHandlerInterceptor {

    private final InitCache initCache;

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) {
        Object handlerBean;
        Method method;
        try {
            handlerBean = ((HandlerMethod) handler).getBean();
            method = ((HandlerMethod) handler).getMethod();
        } catch (Exception e) {
            return true;
        }
        Secure secure = AnnotationUtils.findAnnotation(method, Secure.class);
        if (Objects.isNull(secure)) {
            //不存在往上找
            secure = AnnotationUtils.findAnnotation(handlerBean.getClass(), Secure.class);
        }
        Integer currentWorkerId;
        PatternContext sessionUser;
        if (secure == null || secure.value() == -1) {
            // 如果secure为空，则直接通过
            sessionUser = new PatternContext();
            setLocal(request, sessionUser);
            ContextLocalCache.set(sessionUser);
            return true;
        } else if (secure.value() >= 0) {
            // 验证是否存在会话
            String token = ServletTool.getToken(request);
            if (!JwtUtil.verify(token)) {
                ResponseData.sendClient(response, new ResponseData<>(ResponseResultStatus.NO_LOGIN));
                return false;
            }
            currentWorkerId = JwtUtil.extractWorkerId(token);
            if (currentWorkerId == null) {
                ResponseData.sendClient(response, new ResponseData<>(ResponseResultStatus.NO_LOGIN));
                return false;
            }
            sessionUser = initCache.userCache.get(token);
            if (Objects.isNull(sessionUser)) {
                ResponseData.sendClient(response, new ResponseData<>(ResponseResultStatus.NO_LOGIN));
                return false;
            }
            setLocal(request, sessionUser);
            ContextLocalCache.set(sessionUser);
            if (CollectionUtil.isNotEmpty(sessionUser.getRoleId()) && sessionUser.getRoleId().contains(DefaultSystemConstant.DEFAULT_ROLE)) {
                return true;
            }
        }

        return true;
    }

    private void setLocal(HttpServletRequest request, PatternContext sessionUser) {
        CacheGetResult<Map<String, String>> localResult = initCache.sessionLocal.GET(CacheKeyConstant.UserKey.SESSION_SOCKET_KEY);
        if (localResult.isSuccess()) {
            Map<String, String> value = localResult.getValue();
            if (CollectionUtil.isNotEmpty(value)) {
                String local = value.get(request.getSession().getId());
                sessionUser.setSessionLocal(local);
                return;
            }
        }
        if(StringUtils.isBlank(sessionUser.getLocal())){
            sessionUser.setSessionLocal(SpringTool.getBean(ParentLocale.class).getLocal().toString());
        }else{
            sessionUser.setSessionLocal(sessionUser.getLocal());
        }
    }
}
